/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - geometry/mesh
// Copyright( c) 2015.  All Rights Reserved
//
// File:		AEStaticMesh.cpp
// Author:		Gianluca Belardelli
// Date:		05/05/2015
//
/////////////////////////////////////////////////////////////////////////
#include <AEEngine.h>

////////////////////////////////////////////
// Static Methods
////////////////////////////////////////////
AEStaticMesh *AEStaticMesh::LoadStaticMesh( const char *lpFilename )
{
	return AENULL;
}

AEMeshManager &AEStaticMesh::GetResourceManager( void )
{
	return (AEMeshManager &)*AEngine::GetTextureManager();
}

AEStaticMesh *AEStaticMesh::CreateSphereMesh( void )
{
	AEStaticMeshPtr spSphere = new AEStaticMesh();
	spSphere->AllocateSubmeshes(1);

	AEStaticSubmesh *lpSubMesh = spSphere->GetSubmesh(0);
	lpSubMesh->SetRenderRange( 0, 15 );
	lpSubMesh->SetRenderVertexRange( 0, 8 );


	return spSphere;
}

AEStaticMesh *AEStaticMesh::CreateCubeMesh( AEPrimitiveType ePrimType, AEFLOAT32 fCubeWidth )
{
	AEStaticMeshPtr spCube = new AEStaticMesh();
	spCube->AllocateSubmeshes(1);

	AEStaticSubmesh *lpSubMesh = spCube->GetSubmesh(0);
	lpSubMesh->SetRenderRange( 0, 15 );
	lpSubMesh->SetRenderVertexRange( 0, 8 );


	return spCube;
}

AEStaticMesh *AEStaticMesh::CreatePlaneMesh( void )
{
	return AENULL;
}


////////////////////////////////////////////
// Public Methods
////////////////////////////////////////////
AEStaticMesh::AEStaticMesh( void ) : AEBaseMesh( AEMESHTYPE_STATICMESH ), m_lpSubmeshes( AENULL )
{
}

AEStaticMesh::AEStaticMesh( const char *lpFileName ) : AEBaseMesh( lpFileName, AEMESHTYPE_STATICMESH ), m_lpSubmeshes( AENULL )
{
}

AEStaticMesh::~AEStaticMesh( void )
{
	if( m_lpSubmeshes != AENULL )
		FreeSubmeshes();
}

void AEStaticMesh::AllocateSubmeshes( AEINT32 nNumMeshes )
{
	AEASSERT( nNumMeshes > 0 );
	if( m_lpSubmeshes != AENULL )
		FreeSubmeshes();

	// Alloca con il placement un array di nNumMeshes
	AEMemoryManager *lpPtr = AEMemoryManager::GetInstancePtr();
	m_lpSubmeshes = (AEStaticSubmesh *) ( AEngine::GetMemManager()->GetHeapAllocator().BlockAlloc( nNumMeshes * sizeof( AEStaticSubmesh ) ) );
	AEStaticSubmesh *lpPlacement = m_lpSubmeshes;
	
	for( AEINT32 i=0; i<nNumMeshes; i++ )
	{
		lpPlacement = new ( lpPlacement ) AEStaticSubmesh();
		lpPlacement++;
	}

	m_nNumSubmeshes = nNumMeshes;

	for( AEINT32 i=0; i<m_nNumSubmeshes; i++ )
		m_lpSubmeshes[i].SetMesh( this );
}

void AEStaticMesh::FreeSubmeshes( void )
{
	AEASSERT( m_lpSubmeshes != AENULL );
	AEngine::GetMemManager()->GetHeapAllocator().BlockFree( m_lpSubmeshes, m_nNumSubmeshes * sizeof( AEStaticSubmesh ) );
	m_lpSubmeshes = AENULL;
}

AEBaseSubmesh *AEStaticMesh::GetBaseSubmesh( AEINT32 nMeshIndex ) const
{
	AEASSERT( nMeshIndex >= 0 && nMeshIndex < m_nNumSubmeshes );
	return (AEBaseSubmesh *)&m_lpSubmeshes[ nMeshIndex ];
}

AEStaticMeshInstance *AEStaticMesh::CreateInstance( const AEMatrix4f &matTransform, AEStaticMeshInstance *lpInstance )
{
	return CreateInstance( matTransform, lpInstance, AEFALSE );
}

AEStaticMeshInstance *AEStaticMesh::CreateInstance( const AEMatrix4f &matTransform, AEStaticMeshInstance *lpInstance, AEBOOL32 bNotifyPhysics )
{
	AEStaticMeshInstance *lpRet;
	
	if( lpInstance != AENULL )
	{
		AEASSERT_MSG( lpInstance->GetMesh() == AENULL, "Il puntatore alla Mesh viene sovrascritto" );
		lpRet = lpInstance;
	}
	else
	{
		lpRet = new AEStaticMeshInstance();
	}

	lpRet->m_spMesh = this;

	AEINT32 nSubmeshCount = GetSubmeshCount();
	lpRet->AllocateSubmeshInstances( nSubmeshCount );

	for( AEINT32 i=0; i<nSubmeshCount; i++ )
	{
		AEStaticSubmeshInstance *lpSubmesh = lpRet->GetSubmeshInstance( i );
		AEStaticSubmesh *lpPtr = GetSubmesh( i );
		lpSubmesh->m_lpSubmesh = lpPtr;
		lpSubmesh->m_eGeometryType = AESTATICGEOMTYPE_MESHINSTANCE;
		lpSubmesh->m_bbBoundingBox = this->m_bbBoundingBox;
		lpSubmesh->m_lpMeshInstance = lpRet;
	}

	lpRet->SetTransform( matTransform );
	lpRet->SetDefaultClipSettings();
	lpRet->SetClipMode();

	return lpRet;
}

void AEStaticMesh::AccumulateMemoryFootprint( size_t &iUniqueSys, size_t &iUniqueGPU, size_t &iDependentSys, size_t &iDependentGPU )
{
}

AEBOOL32 AEStaticMesh::Unload( void )
{
	return AEFALSE;
}

AEBOOL32 AEStaticMesh::Reload( void )
{
	return AEFALSE;
}

AEBOOL32 AEStaticMesh::IsLoadFromFile( void ) const
{
	return m_bLoadFromFile;
}


////////////////////////////////////////////
// Protected Methods
////////////////////////////////////////////
void AEStaticMesh::_init( void )
{
}

AEBOOL32 AEStaticMesh::LoadFromFile( const char *lpFilename )
{
	return AEFALSE;
}
